using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using MEA.AE_Data;

namespace MEA.Chart
{
	public class Graph
	{
		private struct Acc
		{
			public object fun;

			public bool isPoint;

			public int nr;

			public float dist;

			public PointF selPoint;

			public int myXpos;
		}

		public Bitmap bmp;

		private List<Function> functions;

		private int width;

		private int height;

		public Graphics g;

		private Color bg_color;

		[Category("Style")]
		[Description("Backgroundcolor")]
		public Color BgColor
		{
			get
			{
				return bg_color;
			}
			set
			{
				bg_color = value;
			}
		}

		[Category("Graphics")]
		[Description("Aliasing")]
		public SmoothingMode Aliasing
		{
			get
			{
				return g.SmoothingMode;
			}
			set
			{
				g.SmoothingMode = value;
			}
		}

		public int Width
		{
			get
			{
				return width;
			}
		}

		public int Height
		{
			get
			{
				return height;
			}
		}

		public Graph(int width, int height)
		{
			functions = new List<Function>();
			Resize(width, height);
		}

		public void Resize(int width, int height)
		{
			if (height == 0)
			{
				height = 1;
			}
			if (width == 0)
			{
				width = 1;
			}
			this.width = width;
			this.height = height;
			bmp = new Bitmap(width, height);
			g = Graphics.FromImage(bmp);
			DrawAll();
		}

		public void AddFunction(Function f)
		{
			functions.Add(f);
		}

		public void RemoveFunction(Function f)
		{
			functions.Remove(f);
		}

		public bool DrawAll()
		{
			g.Clear(bg_color);
			lock (functions)
			{
				foreach (Function function in functions)
				{
					function.koordsyst.Draw(ref g);
				}
				foreach (Function function2 in functions)
				{
					function2.Draw(ref g, true);
				}
			}
			return true;
		}

		public object getClickObj(PointF p, ref int myDataPos)
		{
			object result = null;
			List<Acc> list = new List<Acc>();
			int num = 0;
			Function function = null;
			myDataPos = 0;
			PointF q;
			foreach (Function function2 in functions)
			{
				if (!function2.Visible)
				{
					continue;
				}
				function2.DeSelect();
				Acc item = new Acc
				{
					dist = 0f,
					selPoint = new PointF(0f, 0f)
				};
				q = function2.koordsyst.transformToWert(new PointF[1] { p });
				PointF p2 = new PointF(0f, 0f);
				PointF p3 = new PointF(0f, 0f);
				item.isPoint = function2.isPoint(q, ref p2, ref p3, ref myDataPos);
				if (item.isPoint)
				{
					if (q.X - p2.X < q.X - p2.X)
					{
						item.selPoint = p2;
					}
					else
					{
						item.selPoint = p3;
					}
					p2 = function2.koordsyst.transformToBild((int)p2.X, (int)p2.Y);
					p3 = function2.koordsyst.transformToBild((int)p3.X, (int)p3.Y);
					float num2 = (p3.Y - p2.Y) / (p3.X - p2.X);
					float num3 = p2.Y - num2 * p2.X;
					item.dist = (p.Y - num2 * p.X - num3) / (float)Math.Sqrt(num2 * num2 + 1f);
					if (item.dist < 0f)
					{
						item.dist *= -1f;
					}
					item.fun = function2;
					item.nr = num;
					item.myXpos = myDataPos;
					list.Add(item);
				}
				num++;
			}
			float num4 = 0f;
			q = new PointF(0f, 0f);
			foreach (Acc item2 in list)
			{
				if (item2.isPoint)
				{
					if (function == null)
					{
						num4 = item2.dist;
						function = (Function)item2.fun;
						q = item2.selPoint;
						myDataPos = item2.myXpos;
					}
					else if (num4 > item2.dist)
					{
						num4 = item2.dist;
						function = (Function)item2.fun;
						q = item2.selPoint;
						myDataPos = item2.myXpos;
					}
				}
			}
			if (function != null && (double)q.X != 0.0)
			{
				function.Select();
				function.IsSelected = Function.EGraphicFunctSelect.eSelected;
				function.selected_point = q;
				result = function;
			}
			return result;
		}

		public object MoveSelection(bool left, ref int n, ConfigBase.EGraphicAspect aspect)
		{
			object result = null;
			n = -1;
			foreach (Function function in functions)
			{
				if (function.Visible && function.IsSelected == Function.EGraphicFunctSelect.eSelected && function.SelectNeighborPoint(left, ref n, aspect))
				{
					result = function;
					break;
				}
			}
			return result;
		}

		public void MoveAll(float x, float y)
		{
			foreach (Function function in functions)
			{
				function.koordsyst.offsetWert(x, y);
			}
			DrawAll();
		}

		public void ZoomAll(float factor)
		{
			foreach (Function function in functions)
			{
				function.koordsyst.zoom(factor);
			}
			DrawAll();
		}

		public void Dispose()
		{
			bmp.Dispose();
			functions.Clear();
			g.Dispose();
		}
	}
}
